home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
intrlib1.zip
/
INTR_DJG.CC
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-10
|
37KB
|
1,083 lines
/******************************************************************************
* Low level graphics routines(DJGPP driver). *
* *
* This file is compiled in C++ mode. *
* *
* Written by Gershon Elber, Feb. 1992 *
*******************************************************************************
* Supported device: *
* DJGPP devices. *
*******************************************************************************
* History: *
* 17 Feb 92 - Version 1.0 by Gershon Elber - support for DJGPP. *
******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <ctype.h>
#include <graphics.h>
#ifdef DJGCC
#include <pc.h>
#endif /* DJGCC */
#include "intr_loc.h"
#include "intr_gr.h"
#define POINT_SIZE 0.05 /* Size of + marker drawn. */
#define POINT_TITLE 0.02 /* Distance between point title and + marker. */
#define HISTORY_SIZE 10 /* History buffer length for GRGetGraphicLine. */
#define GR_LINE_LEN 80 /* Maximum chars read by GRGetGraphicLine. */
#define CURSOR_IMAGE_X 24
#define CURSOR_IMAGE_Y 24
#define CURSOR_TYPE_STACK_SIZE 20 /* Size of stack to save cursor types. */
#define VIEW_PORT_STACK_SIZE 20 /* Depth of view port setting stack. */
#define TEXT_SETTING_STACK_SIZE 10 /* Depth of text setting stack. */
#define MAP_UP_X(x) ((((x) - GRPanFactorX) << GRZoomFactor) + GRWidth2)
#define MAP_UP_Y(y) ((((y) - GRPanFactorY) << GRZoomFactor) + GRHeight2)
#define MAP_DN_X(x) ((((x) - GRPanFactorX) >> GRIZoomFactor) + GRWidth2)
#define MAP_DN_Y(y) ((((y) - GRPanFactorY) >> GRIZoomFactor) + GRHeight2)
#define INVMAP_UP_X(x) ((((x) - GRWidth2) >> GRZoomFactor) + GRPanFactorX)
#define INVMAP_UP_Y(y) ((((y) - GRHeight2) >> GRZoomFactor) + GRPanFactorY)
#define INVMAP_DN_X(x) ((((x) - GRWidth2) << GRIZoomFactor) + GRPanFactorX)
#define INVMAP_DN_Y(y) ((((y) - GRHeight2) << GRIZoomFactor) + GRPanFactorY)
typedef struct TextJustifyStruct {
GRTextHorizJustifyType HorizJustify;
GRTextVertJustifyType VertJustify;
} TextJustifyStruct;
typedef struct ImageSaveStruct {
int Width, Height;
char *Data;
} ImageSaveStruct;
int GRScreenMaxX, GRScreenMaxY; /* The maximum resolution of the screen. */
int GRScreenMaxColors; /* The maximum # of colors available. */
IntrRType GRScreenAspect = 1.0; /* Screen aspect ratio (pixel width/height). */
int GRCurrentCursorX, GRCurrentCursorY; /* Cursor current position. */
int GRFontName, GRFontSize; /* Global information on font used. */
int GRDrawText; /* If can not zoom down text, force draw. */
int GRGraphMode = 0, GRGraphDriver = 0; /* What driver/mode are we in. */
static int GRScreenMaxX2, GRScreenMaxY2; /* Half of maximum resolution. */
static VoidPtr GRPutImage = NULL; /* If not null, used to save getimage. */
static int GRScreenGraphicMode;
static int GRTextSize = 1; /* Current text size: 1 = 8x8, 2 = 16x16 etc.. */
static int GRWidth2 = 100;
static int GRHeight2 = 100;
static int GRMinX = 0;
static int GRMinY = 0;
static int GRZoomFactor = 0;
static int GRIZoomFactor = 0;
static int GRPanFactorX = 0;
static int GRPanFactorY = 0;
static int ViewPortStackPtr = 0;
static int GRCrntColor = WHITE; /* Current drawing color. */
static int GRDrawMode = 0x00; /* 0x00 for COPY, 0x100 for XOR mode. */
static int GRLastMoveToX , GRLastMoveToY;
static int CrntHorizCenter = GR_TEXT_HJUSTIFY_CENTER;
static int CrntVertCenter = GR_TEXT_VJUSTIFY_CENTER;
static struct ImageSaveStruct *CursorImageBuffer = NULL;
static struct GrRegion *ViewPortStack[VIEW_PORT_STACK_SIZE];
static int TextSettingStackPtr = 0;
static struct TextJustifyStruct TextSettingStack[TEXT_SETTING_STACK_SIZE];
IntrInt2PtrFunc GlblGetChFunc = IntrGetEventWait;
static char HistoryBuffer[HISTORY_SIZE][GR_LINE_LEN + 1];
static int HistoryBufLen = 0;
static struct GrRegion *ScrnRegion, *CrntRegion;
static void GRComputeTextOffset(char *s, int *x, int *y);
static void MoveOverlapMem(char *Dest, char *Src, int Len);
static int GRGetKey(void);
/****************************************************************************
* Routine to reset all the system to starting condition : *
****************************************************************************/
void GRInitGraph()
{
int i, j, GRScreenErrorCode;
if (GRScreenGraphicMode) return;
ViewPortStackPtr = 0; /* Make sure view port stack is empty. */
GrSetMode(GR_default_graphics);
ScrnRegion = GrScreenRegion();
GRScreenMaxX = ScrnRegion->width;
GRScreenMaxY = ScrnRegion->height;
GRScreenMaxX2 = GRScreenMaxX / 2;
GRScreenMaxY2 = GRScreenMaxY / 2;
GRCurrentCursorX = GRScreenMaxX2;
GRCurrentCursorY = GRScreenMaxY2;
GRScreenMaxColors = 256;
ScrnRegion->Box(0, 0, GRScreenMaxX, GRScreenMaxY, BLACK);
CrntRegion = ScrnRegion;
/* Prepare the cursor (Arrow) image : */
GRSetColor(GRScreenMaxColors - 1);
GRSLine(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
j = CURSOR_IMAGE_X / 3;
for (i = 1; i <= 7; i++) GRSLine(0, 0, j, j + i);/* Draw the arrow head. */
j = CURSOR_IMAGE_Y / 3;
for (i = 1; i <= 7; i++) GRSLine(0, 0, j + i, j);
CursorImageBuffer = (struct ImageSaveStruct *)
GRGetImageBuffer(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
GRClearAllScreen();
GRScreenGraphicMode = TRUE;
}
/****************************************************************************
* Routine to close and shutdown graphic mode : *
****************************************************************************/
void GRCloseGraph(void)
{
if (!GRScreenGraphicMode) return;
GrSetMode(GR_default_text);
}
/****************************************************************************
* Routine to set line style parameters. *
****************************************************************************/
void GRSetLineStyle(int LineStyle, unsigned int Pattern, int Thickness)
{
}
/****************************************************************************
* Routine to set fill style parameters. *
****************************************************************************/
void GRSetFillStyle(int Pattern, int Color)
{
GRCrntColor = Color;
}
/****************************************************************************
* Routine to set write mode parameters - non zero XOR mode, zero COPY mode. *
****************************************************************************/
void GRSetWriteMode(int DrawMode)
{
GRDrawMode = DrawMode ? 0x100 : 0x00;
}
/****************************************************************************
* Routine to set text horizontal and vertical justification. *
****************************************************************************/
void GRSetTextJustify(int HorizCenter, int VertCenter)
{
CrntHorizCenter = HorizCenter;
CrntVertCenter = VertCenter;
}
/****************************************************************************
* Routine to set zoom factor for drawing. *
* Zoom factor of 0 means regular drawing while each inc/decremenet zooms *
* up/down respectively by a factor of 2. *
****************************************************************************/
void GRSetZoomFactor(int ZoomFactor)
{
GRZoomFactor = ZoomFactor;
GRIZoomFactor = -GRZoomFactor;
}
/****************************************************************************
* Routine to set pan factors for drawing space. *
****************************************************************************/
void GRSetPanFactors(int PanFactorX, int PanFactorY)
{
GRPanFactorX = PanFactorX;
GRPanFactorY = PanFactorY;
}
/****************************************************************************
* Routine to set text drawing parameters, in drawing space. *
****************************************************************************/
void GRSetTextStyle(int GRFontName, int Direction, int Size)
{
GRTextSize = Size + GRZoomFactor;
}
/****************************************************************************
* Routine to set text drawing parameters, in screen space. *
****************************************************************************/
void GRSetSTextStyle(int GRFontName, int Direction, int Size)
{
}
/****************************************************************************
* Routine to get an image rectangle into real memory. *
****************************************************************************/
void *GRGetImageBuffer(int x1, int y1, int x2, int y2)
{
int i, Width;
struct ImageSaveStruct
*Buffer = new struct ImageSaveStruct;
char *p,
*Visual = (char *) (0xd0000000 +
(CrntRegion -> abs_y + y1) * GRScreenMaxX +
(CrntRegion -> abs_x + x1));
Width = Buffer -> Width = x2 - x1 + 1;
Buffer -> Height = y2 - y1 + 1;
Buffer -> Data = p = new char[Buffer -> Width * Buffer -> Height];
for (i = Buffer -> Height; i > 0; i--) {
memcpy(p, Visual, Width);
p += Width;
Visual += GRScreenMaxX;
}
return (void *) Buffer;
}
/****************************************************************************
* Routine to put an image rectangle from real memory into the display. *
****************************************************************************/
void GRPutImageBuffer(int x1, int y1, void *Buffer)
{
struct ImageSaveStruct
*IBuffer = (ImageSaveStruct *) Buffer;
int i,
Width = IBuffer -> Width;
char
*p = IBuffer -> Data,
*Visual = (char *) (0xd0000000 +
(CrntRegion -> abs_y + y1) * GRScreenMaxX +
(CrntRegion -> abs_x + x1));
for (i = IBuffer -> Height; i > 0; i--) {
memcpy(Visual, p, Width);
p += Width;
Visual += GRScreenMaxX;
}
delete IBuffer -> Data;
delete IBuffer;
}
/****************************************************************************
* Routine to draw the cursor as an arrow. *
****************************************************************************/
void GRPutArrowCursor(int x, int y)
{
int i, j,
CursorWidth = CursorImageBuffer -> Width,
Width = MIN(CursorWidth, GRScreenMaxX - x);
char *cp, *vp,
*CursorData = CursorImageBuffer -> Data,
*VisualData = (char *) (0xd0000000 + y * GRScreenMaxX + x);
for (i = CursorImageBuffer -> Height; i > 0; i--) {
cp = CursorData;
vp = VisualData;
for (j = 0; j < Width; j++) *vp++ ^= *cp++;
CursorData += CursorWidth;
VisualData += GRScreenMaxX;
}
}
/****************************************************************************
* Routine to XOR a rectangle area on screen using current color. *
****************************************************************************/
void GRXORRectangle(int x1, int y1, int x2, int y2)
{
ScrnRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | 0x100);
}
/****************************************************************************
* External reference for the mappings. *
****************************************************************************/
int GRMapX(int x)
{
return (GRZoomFactor > 0 ? MAP_UP_X(x) : MAP_DN_X(x)) + GRMinX;
}
int GRMapY(int y)
{
return (GRZoomFactor > 0 ? MAP_UP_Y(y) : MAP_DN_Y(y)) + GRMinY;
}
/****************************************************************************
* External reference for the inverse mapping. *
****************************************************************************/
int GRInvMapX(int x)
{
x -= GRMinX;
return (GRZoomFactor > 0 ? INVMAP_UP_X(x) : INVMAP_DN_X(x));
}
int GRInvMapY(int y)
{
y -= GRMinY;
return (GRZoomFactor > 0 ? INVMAP_UP_Y(y) : INVMAP_DN_Y(y));
}
/****************************************************************************
* Routine to draw a line, in Object spaces. *
****************************************************************************/
void GRLine(int x1, int y1, int x2, int y2)
{
if (GRZoomFactor > 0) {
CrntRegion->Line(MAP_UP_X(x1),
MAP_UP_Y(y1),
GRLastMoveToX = MAP_UP_X(x2),
GRLastMoveToY = MAP_UP_Y(y2),
GRCrntColor);
}
else {
CrntRegion->Line(MAP_DN_X(x1),
MAP_DN_Y(y1),
GRLastMoveToX = MAP_DN_X(x2),
GRLastMoveToY = MAP_DN_Y(y2),
GRCrntColor);
}
}
/****************************************************************************
* Routine to move to a new position, in Object space. *
****************************************************************************/
void GRMoveTo(int x, int y)
{
if (GRZoomFactor > 0) {
GRLastMoveToX = MAP_UP_X(x);
GRLastMoveToY = MAP_UP_Y(y);
}
else {
GRLastMoveToX = MAP_DN_X(x);
GRLastMoveToY = MAP_DN_Y(y);
}
}
/****************************************************************************
* Routine to draw to a new position, in Object space. *
****************************************************************************/
void GRLineTo(int x, int y)
{
int GRLineToX, GRLineToY;
if (GRZoomFactor > 0) {
GRLineToX = MAP_UP_X(x);
GRLineToY = MAP_UP_Y(y);
}
else {
GRLineToX = MAP_DN_X(x);
GRLineToY = MAP_DN_Y(y);
}
CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
GRCrntColor | GRDrawMode);
GRLastMoveToX = GRLineToX;
GRLastMoveToY = GRLineToY;
}
/****************************************************************************
* Routine to move to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSMoveTo(int x, int y)
{
GRLastMoveToX = x;
GRLastMoveToY = y;
}
/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSLineTo(int x, int y)
{
CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, x, y,
GRCrntColor | GRDrawMode);
GRLastMoveToX = x;
GRLastMoveToY = y;
}
/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSLine(int x1, int y1, int x2, int y2)
{
CrntRegion->Line(x1, y1, x2, y2, GRCrntColor | GRDrawMode);
GRLastMoveToX = x2;
GRLastMoveToY = y2;
}
/****************************************************************************
* Routine to move to a new position relative to current one, as in Object *
* space. *
****************************************************************************/
void GRMoveRel(int x, int y)
{
if (GRZoomFactor > 0) {
GRLastMoveToX += x << GRZoomFactor;
GRLastMoveToY += y << GRZoomFactor;
}
else {
GRLastMoveToX += x >> GRIZoomFactor;
GRLastMoveToY += y >> GRIZoomFactor;
}
}
/****************************************************************************
* Routine to line to a new position relative to current one, as in Object *
* space. *
****************************************************************************/
void GRLineRel(int x, int y)
{
int GRLineToX = GRLastMoveToX,
GRLineToY = GRLastMoveToY;
if (GRZoomFactor > 0) {
GRLineToX += x << GRZoomFactor;
GRLineToY += y << GRZoomFactor;
}
else {
GRLineToX += x >> GRIZoomFactor;
GRLineToY += y >> GRIZoomFactor;
}
CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
GRCrntColor | GRDrawMode);
GRLastMoveToX = GRLineToX;
GRLastMoveToY = GRLineToY;
}
/****************************************************************************
* Routine to move to a new position relative to current one, as in Screen *
* space (pixel coords.). *
****************************************************************************/
void GRSMoveRel(int x, int y)
{
GRLastMoveToX += x;
GRLastMoveToY += y;
}
/****************************************************************************
* Routine to line to a new position relative to current one, as in Screen *
* space (pixel coords.). *
****************************************************************************/
void GRSLineRel(int x, int y)
{
int GRLineToX = GRLastMoveToX + x,
GRLineToY = GRLastMoveToY + y;
CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
GRCrntColor | GRDrawMode);
GRLastMoveToX = GRLineToX;
GRLastMoveToY = GRLineToY;
}
/****************************************************************************
* Routine to draw a new polyline and fill it if Fill, in screen space. *
****************************************************************************/
void GRPoly(int n, int *Points, int Fill)
{
int i, ii;
if (GRZoomFactor > 0)
for (i = 0; i < n; i++) {
ii = i << 1;
Points[ii] = MAP_UP_X(Points[ii]);
Points[ii + 1] = MAP_UP_Y(Points[ii + 1]);
}
else
for (i = 0; i < n; i++) {
ii = i << 1;
Points[ii] = MAP_DN_X(Points[ii]);
Points[ii + 1] = MAP_DN_Y(Points[ii + 1]);
}
if (Fill) {
/* There is a problem with BLACK color that fillpoly sometime does */
/* not clear the border properly, so we need to redo it by drawpoly. */
IntrFatalError("Fill not supported in this driver.\n");
}
else {
GRSMoveTo(Points[n * 2 - 2], Points[n * 2 - 1]);
for (i = 0; i < n; i++) {
ii = i << 1;
GRSLineTo(Points[ii], Points[ii + 1]);
}
}
}
/****************************************************************************
* Routine to draw a bar, in drawing space. *
****************************************************************************/
void GRBar(int x1, int y1, int x2, int y2)
{
if (GRZoomFactor > 0) {
x1 = MAP_UP_X(x1);
y1 = MAP_UP_Y(y1);
x2 = MAP_UP_X(x2);
y2 = MAP_UP_Y(y2);
}
else {
x1 = MAP_DN_X(x1);
y1 = MAP_DN_Y(y1);
x2 = MAP_DN_X(x2);
y2 = MAP_DN_Y(y2);
}
CrntRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | GRDrawMode);
}
/****************************************************************************
* Routine to draw a bar, in screen space. *
****************************************************************************/
void GRSBar(int x1, int y1, int x2, int y2)
{
CrntRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | GRDrawMode);
}
/****************************************************************************
* Routine to draw a circle, in drawing space. *
****************************************************************************/
void GRCircle(int x, int y, int r)
{
IntrFatalError("Fill not supported in this driver.\n");
}
/****************************************************************************
* Routine to draw an arc, in drawing space. *
* As the Y axes is inverted the Angles should be inverted as well. *
****************************************************************************/
void GRArc(int x, int y, int StAngle, int EndAngle, int r)
{
IntrFatalError("Fill not supported in this driver.\n");
}
/****************************************************************************
* Routine to draw the given text in given drawing space coordinates. *
****************************************************************************/
IntrBType GRDrawingText(void)
{
return GRTextSize > 0 || GRDrawText;
}
/****************************************************************************
* Routine to compute text justification offset according to given string. *
****************************************************************************/
static void GRComputeTextOffset(char *s, int *x, int *y)
{
int Width = GRGetTextWidth(s),
Height = GRGetTextHeight(s);
switch (CrntHorizCenter) {
case GR_TEXT_HJUSTIFY_LEFT:
*x = 0;
break;
case GR_TEXT_HJUSTIFY_CENTER:
*x = -Width/ 2;
break;
case GR_TEXT_HJUSTIFY_RIGHT:
*x = -Width;
break;
}
switch (CrntVertCenter) {
case GR_TEXT_VJUSTIFY_BOTTOM:
*y = -Height;
break;
case GR_TEXT_VJUSTIFY_CENTER:
*y = -Height / 2;
break;
case GR_TEXT_VJUSTIFY_TOP:
*y = 0;
break;
}
}
/****************************************************************************
* Routine to draw the given text in given drawing space coordinates. *
****************************************************************************/
void GRText(int x, int y, char *s)
{
int XOffset, YOffset;
GRComputeTextOffset(s, &XOffset, &YOffset);
/* If text can not be zoom down and we are not forced to draw - dont. */
if (GRTextSize < 1 && !GRDrawText) return;
if (GRZoomFactor > 0)
CrntRegion->Text(MAP_UP_X(x) + XOffset, MAP_UP_Y(y) + YOffset,
s, GRCrntColor, -1);
else
CrntRegion->Text(MAP_DN_X(x) + XOffset, MAP_DN_Y(y) + YOffset,
s, GRCrntColor, -1);
}
/****************************************************************************
* Routine to draw the given text in given screen space coordinates. *
****************************************************************************/
void GRSText(int x, int y, char *s)
{
int XOffset, YOffset;
GRComputeTextOffset(s, &XOffset, &YOffset);
CrntRegion->Text(x + XOffset, y + YOffset, s, GRCrntColor, -1);
}
/****************************************************************************
* Routine to draw the given text in given screen space coordinates. *
* A Black shadow is drawn for the given string. *
****************************************************************************/
void GRSTextShadow(int x, int y, int Color, char *s)
{
int XOffset, YOffset;
GRComputeTextOffset(s, &XOffset, &YOffset);
CrntRegion->Text(x + 2 + XOffset, y + 2 + YOffset, s, BLACK, -1);
CrntRegion->Text(x + XOffset, y + YOffset, s, Color, -1);
}
/****************************************************************************
* Routine to get string width in pixel. *
****************************************************************************/
int GRGetTextWidth(char *Str)
{
return 8 * strlen(Str);
}
/****************************************************************************
* Routine to get string height in pixel. *
****************************************************************************/
int GRGetTextHeight(char *Str)
{
return 16;
}
/****************************************************************************
* Routine to push current font type and text attributes. *
****************************************************************************/
void GRPushTextSetting(void)
{
if (TextSettingStackPtr >= TEXT_SETTING_STACK_SIZE)
IntrFatalError("Text setting stack overflow.");
TextSettingStack[TextSettingStackPtr].HorizJustify = CrntHorizCenter;
TextSettingStack[TextSettingStackPtr++].VertJustify = CrntVertCenter;
}
/****************************************************************************
* Routine to pop current font type and text attributes. *
****************************************************************************/
void GRPopTextSetting(void)
{
if (--TextSettingStackPtr < 0)
IntrFatalError("Text setting stack underflow.");
CrntHorizCenter = TextSettingStack[TextSettingStackPtr].HorizJustify;
CrntVertCenter = TextSettingStack[TextSettingStackPtr].VertJustify;
}
/****************************************************************************
* Routine to set color to color within range. *
****************************************************************************/
void GRSetColor(int Color)
{
if (Color >= GRScreenMaxColors)
Color = Color % (GRScreenMaxColors - 1) + 1;
GRCrntColor = Color;
}
/****************************************************************************
* Routine to get current active color. *
****************************************************************************/
int GRGetColor(void)
{
return GRCrntColor;
}
/****************************************************************************
* Routine to set one color index RGB values. *
****************************************************************************/
void GRSetRGBPalette(int Index, int Red, int Green, int Blue)
{
GrSetColor(Index, Red, Green, Blue);
}
/*****************************************************************************
* Routine to clear all the screen. *
*****************************************************************************/
void GRClearAllScreen(void)
{
ScrnRegion->Box(0, 0, GRScreenMaxX, GRScreenMaxY, BLACK);
}
/*****************************************************************************
* Routine to clear given rectangle viewport. *
*****************************************************************************/
void GRClearViewPort(int x1, int y1, int x2, int y2)
{
ScrnRegion->Box(x1, y1, x2, y2, BLACK);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void _GRSetViewPort(int x1, int y1, int x2, int y2)
{
_GRSetViewPort2(x1, y1, x2, y2, TRUE);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void _GRSetViewPort2(int x1, int y1, int x2, int y2, IntrBType Clip)
{
if (CrntRegion != ScrnRegion)
delete CrntRegion;
CrntRegion = ScrnRegion->SubRegion(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void GRGetViewPort(int *x1, int *y1, int *x2, int *y2)
{
*x1 = CrntRegion -> abs_x;
*y1 = CrntRegion -> abs_y;
*x2 = CrntRegion -> width + CrntRegion -> abs_x - 1;
*y2 = CrntRegion -> height + CrntRegion -> abs_y - 1;
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void GRSetViewPort(int x1, int y1, int x2, int y2)
{
_GRSetViewPort2(x1, y1, x2, y2, TRUE);
GRWidth2 = (x2 - x1) / 2;
GRHeight2 = (y2 - y1) / 2;
GRMinX = x1;
GRMinY = y1;
}
/*****************************************************************************
* Routine to push current view port. *
*****************************************************************************/
void GRPushViewPort(void)
{
if (ViewPortStackPtr >= VIEW_PORT_STACK_SIZE)
IntrFatalError("View port stack overflow.");
ViewPortStack[ViewPortStackPtr++] = CrntRegion;
CrntRegion = ScrnRegion;
}
/*****************************************************************************
* Routine to pop current view port. *
*****************************************************************************/
void GRPopViewPort(void)
{
if (--ViewPortStackPtr < 0)
IntrFatalError("View port stack underflow.");
CrntRegion = ViewPortStack[ViewPortStackPtr];
GRWidth2 = CrntRegion->width / 2;
GRHeight2 = CrntRegion->height / 2;
GRMinX = CrntRegion->abs_x;
GRMinY = CrntRegion->abs_y;
}
/*****************************************************************************
* Routine to read one line terminated by <Enter> and visualized on graphic *
* screen. *
* Full line editing is supported which includes: *
* 1. Right and left arrows to move along the line. *
* 2. Up and down arrows to cirlce along a history buffer. *
* 3. Delete to delete current character. *
* 4. Insert to toggle Insert/Overwrite mode. *
* 5. Backspace to delete character before current one. *
* 6. Home/End to move to beginning/End of string respectively. *
* 7. Return to accept current line. *
* 8. Esc to clear current line. *
* If s is not empty it is used as starting string. *
* Line is drawn starting from position x, y on screen (normalized -1..1). *
*****************************************************************************/
void GRGetGraphicLine(int WindowID, int x, int y, char s[], int SLen,
int WindowLen, int ForeColor, int BackColor)
{
static int
Insert = TRUE;
int NextKey, FirstVisible, i,
Xstep = 8, /* Basically the font size. */
Len = strlen(s),
CursorPos = Len,
FirstTime = TRUE,
EndOfString = FALSE,
HistoryBufCrnt = -1;
char DisplayLine[GR_LINE_LEN], *Cursor;
_IntrWindowStruct
*Window = WindowID ? _IntrFindWndwUsingID(WindowID) : NULL;
IntrBBoxStruct
*BBox = Window ? &Window -> BBox : NULL;
struct GrRegion
*WRegion = BBox ? ScrnRegion->SubRegion(BBox -> Xmin,
BBox -> Ymin,
BBox -> Xmax - BBox -> Xmin + 1,
BBox -> Ymax - BBox -> Ymin + 1)
: ScrnRegion;
GRPushTextSetting();
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
while (!EndOfString) {
/* Can not display the whole string, so set first visible char: */
FirstVisible = CursorPos > WindowLen - 2 ? CursorPos - WindowLen + 2
: 0;
/* Prepare the part of s to be displayed: */
strncpy(DisplayLine, &s[FirstVisible], GR_LINE_LEN - 1);
DisplayLine[MIN(WindowLen, GR_LINE_LEN - 1)] = 0;
Cursor = (Insert ? "_" : "-");
WRegion->Text(x, y, DisplayLine, ForeColor, BackColor);
WRegion->Text(x + (CursorPos - FirstVisible) * Xstep, y, Cursor,
WHITE, -1);
if ((NextKey = GRGetKey()) != KEY_REFRESH || FirstTime) {
WRegion->Text(x, y, DisplayLine, BackColor, BackColor);
WRegion->Text(x + (CursorPos - FirstVisible) * Xstep, y, Cursor,
BackColor, -1);
}
FirstTime = FALSE;
switch (NextKey) {
case KEY_BSPACE:
if (CursorPos == 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
MoveOverlapMem(&s[CursorPos - 1], &s[CursorPos],
Len - CursorPos + 1);
CursorPos--;
Len--;
break;
case KEY_DELETE:
if (CursorPos >= Len) {
GRTone(1000, 100); /* Do some noise... */
break;
}
MoveOverlapMem(&s[CursorPos], &s[CursorPos + 1],
Len - CursorPos);
Len--;
break;
case KEY_RIGHT:
if (CursorPos >= Len) {
GRTone(1000, 100); /* Do some noise... */
break;
}
CursorPos++;
break;
case KEY_LEFT:
if (CursorPos <= 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
CursorPos--;
break;
case KEY_UP:
if (HistoryBufLen == 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
if (++HistoryBufCrnt >= HistoryBufLen) HistoryBufCrnt = 0;
strcpy(s, HistoryBuffer[HistoryBufCrnt]);
CursorPos = Len = strlen(s);
break;
case KEY_DOWN:
if (HistoryBufLen == 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
if (--HistoryBufCrnt < 0) HistoryBufCrnt = HistoryBufLen - 1;
strcpy(s, HistoryBuffer[HistoryBufCrnt]);
CursorPos = Len = strlen(s);
break;
case KEY_RETURN:
EndOfString = TRUE;
break;
case KEY_ESC:
Len = 0; /* Clear everything. */
CursorPos = 0;
s[0] = 0;
break;
case KEY_HOME:
CursorPos = 0;
break;
case KEY_END:
CursorPos = Len;
break;
case KEY_INSERT:
Insert = !Insert;
break;
case KEY_NONE:
GRTone(1000, 100); /* Do some noise... */
GRTone(500, 200);
break;
case KEY_REFRESH: /* Internal event to intr_lib. */
if (Window != NULL) {
_GRSetViewPort(Window -> BBox.Xmin, Window -> BBox.Ymin,
Window -> BBox.Xmax, Window -> BBox.Ymax);
x = TEXT_BORDER,
y = Window -> BBox.Ymax - Window -> BBox.Ymin -
TEXT_BORDER - GRGetTextHeight("M");
}
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
break;
default: /* Regular ascii char. */
if (Insert) {
MoveOverlapMem(&s[CursorPos + 1], &s[CursorPos],
Len - CursorPos + 1);
Len++;
}
else if (CursorPos == Len)
Len++; /* We are on last character. */
s[CursorPos++] = NextKey;
if (CursorPos == Len) s[CursorPos] = 0;
break;
}
if (SLen <= Len - 1) { /* End of buffer - can not save more info. */
Len = SLen - 1;
if (CursorPos > Len) CursorPos = Len;
GRTone(1000, 100); /* Do some noise... */
}
}
GRPopTextSetting();
/* Update the history buffer: */
for (i = HISTORY_SIZE - 1; i > 0; i--)
strncpy(HistoryBuffer[i], HistoryBuffer[i - 1], GR_LINE_LEN);
strncpy(HistoryBuffer[0], s, GR_LINE_LEN);
HistoryBufLen = MIN(HISTORY_SIZE, HistoryBufLen + 1);
if (WRegion != ScrnRegion) delete WRegion;
}
/*****************************************************************************
* Same as memcpy but allow Src and Dest to overlap. *
*****************************************************************************/
static void MoveOverlapMem(char *Dest, char *Src, int Len)
{
char TempStr[GR_LINE_LEN];
memcpy(TempStr, Src, Len);
memcpy(Dest, TempStr, Len);
}
/*****************************************************************************
* Sets the function invoked to get a kbd event in GRGetKey. *
* NULL will recover the internal default - IntrGetEventWait. *
*****************************************************************************/
void GRSetGetKeyFunc(IntrInt2PtrFunc GetChFunc)
{
if (GetChFunc == NULL)
GlblGetChFunc = IntrGetEventWait;
else
GlblGetChFunc = GetChFunc;
}
/*****************************************************************************
* Get a key from keyboard, and translating operational keys into special *
* codes (>255). *
*****************************************************************************/
static int GRGetKey(void)
{
int x, y;
/* Detach the keyboard from moving the mouse so keyboard can be used to */
/* edit the input line instead. */
_IntrDetachKbdFromMouse = TRUE;
while (GlblGetChFunc(&x, &y) != INTR_EVNT_KEY);
_IntrDetachKbdFromMouse = FALSE;
if (x >= 256) {
switch (x - 256) { /* Extended code - get the next extended char. */
case 72:
return KEY_UP;
case 80:
return KEY_DOWN;
case 75:
return KEY_LEFT;
case 77:
return KEY_RIGHT;
case 71:
return KEY_HOME;
case 79:
return KEY_END;
case 83:
return KEY_DELETE;
case 82:
return KEY_INSERT;
case KEY_REFRESH - 256:
return KEY_REFRESH;
}
}
else {
switch (x) {
case 8:
return KEY_BSPACE;
case 10:
case 13:
return KEY_RETURN;
case 27:
return KEY_ESC;
default:
if (isprint(x)) return x;
}
}
return KEY_NONE;
}
/*****************************************************************************
* Routine to delay the specified amount in millisec. *
*****************************************************************************/
extern "C" void delay(int time)
{
int i,
j = 0;
for (i = 0; i < 50000; i++) j += i + 5; /* basically wait. */
}
/*****************************************************************************
* Routine to make some sound with given Frequency, Time milliseconds: *
*****************************************************************************/
void GRTone(int Frequency, int Duration)
{
sound(Frequency);
delay(Duration);
sound(0);
}